BUILD_DIR = ./build
OUTPUT_DIR = ./output
ENTRY_POINT = 0xc0001500
AS = nasm
CC = gcc
LD = ld
BOOT_LIB = -I boot/include
LIB = -I lib/ -I lib/kernel/inc -I lib/user/inc -I kernel/inc -I device/inc \
	  -I thread/inc -I userprog/inc
ASFLAGS = -f elf
CFLAGS = -Wall $(LIB) -c -m32 -march=i686 -fno-stack-protector\
		 -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS = -m elf_i386 -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map

KERNEL_OBJ = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \
      		 $(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/debug.o \
			 $(BUILD_DIR)/print.o $(BUILD_DIR)/string.o $(BUILD_DIR)/bitmap.o \
			 $(BUILD_DIR)/memory.o $(BUILD_DIR)/thread.o $(BUILD_DIR)/list.o \
			 $(BUILD_DIR)/switch.o $(BUILD_DIR)/console.o $(BUILD_DIR)/sync.o \
			 $(BUILD_DIR)/keyboard.o $(BUILD_DIR)/ioqueue.o $(BUILD_DIR)/tss.o \
			 $(BUILD_DIR)/process.o

BOCHS_BIN_DIR = /home/jianglin/Software/bochs-2.6.2/bin/bochs
BOCHS_HD_DIR = /home/jianglin/Software/bochs-2.6.2/hd60M.img
BOCHS_DISK_DIR = /home/jianglin/Software/bochs-2.6.2/bin/bochsrc.disk

all:distclean mbr loader kernel write run

$(OUTPUT_DIR)/mbr.bin: boot/mbr.S boot/include/boot.inc
	@$(AS) $(BOOT_LIB) boot/mbr.S -o output/mbr.bin
mbr:clean $(OUTPUT_DIR)/mbr.bin

$(OUTPUT_DIR)/loader.bin: boot/loader.S boot/include/boot.inc
	@$(AS) $(BOOT_LIB) boot/loader.S -o output/loader.bin
loader:clean $(OUTPUT_DIR)/loader.bin

$(BUILD_DIR)/main.o: kernel/src/main.c lib/string.h lib/kernel/inc/print.h \
					 lib/stdint.h kernel/inc/init.h kernel/inc/debug.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/init.o: kernel/src/init.c lib/kernel/inc/print.h \
					 lib/stdint.h kernel/inc/init.h \
					 kernel/inc/interrupt.h device/inc/timer.h \
					 kernel/inc/debug.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/interrupt.o: kernel/src/interrupt.c kernel/inc/interrupt.h\
						  kernel/inc/global.h lib/kernel/inc/print.h\
						  lib/kernel/inc/io.h lib/stdint.h kernel/inc/debug.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/timer.o: device/src/timer.c device/inc/timer.h\
					  lib/stdint.h lib/kernel/inc/io.h\
					  lib/kernel/inc/print.h kernel/inc/debug.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/string.o: lib/src/string.c lib/stdint.h\
					   lib/string.h kernel/inc/debug.h\
					   kernel/inc/global.h
	@$(CC) $(CFLAGS) $< -o $@					


$(BUILD_DIR)/debug.o: kernel/src/debug.c kernel/inc/interrupt.h \
					  kernel/inc/debug.h lib/kernel/inc/print.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/bitmap.o: lib/kernel/src/bitmap.c lib/kernel/inc/bitmap.h \
					   kernel/inc/debug.h kernel/inc/global.h \
					   lib/string.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/memory.o: kernel/src/memory.c kernel/inc/memory.h \
					   lib/stdint.h lib/kernel/inc/bitmap.h \
					   lib/kernel/inc/print.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/thread.o: thread/src/thread.c thread/inc/thread.h\
					   kernel/inc/memory.h lib/string.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/list.o: lib/kernel/src/list.c lib/kernel/inc/list.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/sync.o: thread/src/sync.c thread/inc/sync.h\
					 kernel/inc/interrupt.h
	@$(CC) $(CFLAGS) $< -o $@		

$(BUILD_DIR)/keyboard.o: device/src/keyboard.c device/inc/keyboard.h
	@$(CC) $(CFLAGS) $< -o $@	

$(BUILD_DIR)/console.o: device/src/console.c device/inc/console.h
	@$(CC) $(CFLAGS) $< -o $@		

$(BUILD_DIR)/ioqueue.o: lib/kernel/src/ioqueue.c lib/kernel/inc/ioqueue.h 
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/tss.o: userprog/src/tss.c userprog/inc/tss.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/process.o: userprog/src/process.c userprog/inc/process.h
	@$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/kernel.o: kernel/src/kernel.S
	@$(AS) $(ASFLAGS) $< -o $@

$(BUILD_DIR)/print.o: lib/kernel/src/print.S
	@$(AS) $(ASFLAGS) $< -o $@

$(BUILD_DIR)/switch.o: thread/src/switch.S
	@$(AS) $(ASFLAGS) $< -o $@

$(OUTPUT_DIR)/kernel.bin: $(KERNEL_OBJ)
	@$(LD) $(LDFLAGS) $^ -o $@

kernel: clean $(OUTPUT_DIR)/kernel.bin
	

.PHONY: clean distclean mbr loader kernel write run all
clean:
	@cd $(BUILD_DIR) && rm -f ./*
distclean:
	@cd $(BUILD_DIR) && rm -f ./*
	@cd $(OUTPUT_DIR) && rm -f ./*
write:
	@sudo dd if=output/mbr.bin of=$(BOCHS_HD_DIR) bs=512 count=1 conv=notrunc
	@sudo dd if=output/loader.bin of=$(BOCHS_HD_DIR) bs=512 seek=2 count=4 conv=notrunc
	@sudo dd if=output/kernel.bin of=$(BOCHS_HD_DIR) bs=512 seek=9 count=200 conv=notrunc
run:
	@sudo $(BOCHS_BIN_DIR) -f $(BOCHS_DISK_DIR)
	